﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Saxxon.LibDoomSharp.Lumps
{
    public class HexenThingsEntry : SerializableBase
    {
        /// <summary>
        /// Length in bytes of an entry.
        /// </summary>
        public const int ENTRY_LENGTH = 20;

        /// <summary>
        /// Thing ID number for use in scripts.
        /// </summary>
        public UInt16 ID;

        /// <summary>
        /// X-location of the thing in units.
        /// </summary>
        public Int16 LocationX;

        /// <summary>
        /// Y-location of the thing in units.
        /// </summary>
        public Int16 LocationY;

        /// <summary>
        /// Z-location of the thing in units.
        /// </summary>
        public Int16 LocationZ;

        /// <summary>
        /// Angle in degrees of the thing.
        /// </summary>
        public ThingsLumpEntryAngle Angle;

        /// <summary>
        /// Thing type- this will vary among games.
        /// </summary>
        public UInt16 Type;

        /// <summary>
        /// Flags that determine how the thing is processed by the game.
        /// </summary>
        public HexenThingsLumpEntryFlags Flags;

        /// <summary>
        /// Action to execute when the thing is consumed.
        /// </summary>
        public byte Action;

        /// <summary>
        /// Action argument 1.
        /// </summary>
        public byte ActionArg1;

        /// <summary>
        /// Action argument 2.
        /// </summary>
        public byte ActionArg2;

        /// <summary>
        /// Action argument 3.
        /// </summary>
        public byte ActionArg3;

        /// <summary>
        /// Action argument 4.
        /// </summary>
        public byte ActionArg4;

        /// <summary>
        /// Action argument 5.
        /// </summary>
        public byte ActionArg5;

        /// <summary>
        /// Read entry data.
        /// </summary>
        protected override void Read(Stream stream, int length)
        {
            DataReader reader = GetReader(stream);
            ID = reader.ReadUInt16();
            LocationX = reader.ReadInt16();
            LocationY = reader.ReadInt16();
            LocationZ = reader.ReadInt16();
            Angle = (ThingsLumpEntryAngle)reader.ReadUInt16();
            Type = reader.ReadUInt16();
            Flags = (HexenThingsLumpEntryFlags)reader.ReadUInt16();
            Action = reader.ReadByte();
            ActionArg1 = reader.ReadByte();
            ActionArg2 = reader.ReadByte();
            ActionArg3 = reader.ReadByte();
            ActionArg4 = reader.ReadByte();
            ActionArg5 = reader.ReadByte();
        }

        /// <summary>
        /// Return string representation of this entry.
        /// </summary>
        public override string ToString()
        {
            return "Thing { Location=" + LocationX.ToString() + ", " +
                LocationY.ToString() +
                "; Angle=" + Angle.ToString() + 
                "; Flags=" + Flags.ToString() +
                "; Action=" + Action.ToString() + ", " +
                ActionArg1.ToString() + ", " +
                ActionArg2.ToString() + ", " +
                ActionArg3.ToString() + ", " +
                ActionArg4.ToString() + ", " +
                ActionArg5.ToString() +
                "; }";
        }

        /// <summary>
        /// Write entry data.
        /// </summary>
        protected override void Write(Stream stream)
        {
            DataWriter writer = GetWriter(stream);
            writer.WriteUInt16(ID);
            writer.WriteInt16(LocationX);
            writer.WriteInt16(LocationY);
            writer.WriteInt16(LocationZ);
            writer.WriteUInt16((UInt16)Angle);
            writer.WriteUInt16(Type);
            writer.WriteUInt16((UInt16)Flags);
            writer.WriteInt8(Action);
            writer.WriteInt8(ActionArg1);
            writer.WriteInt8(ActionArg2);
            writer.WriteInt8(ActionArg3);
            writer.WriteInt8(ActionArg4);
            writer.WriteInt8(ActionArg5);
        }
    }

    [FlagsAttribute]
    public enum HexenThingsLumpEntryFlags : ushort
    {
        /// <summary>
        /// Thing is present on difficulty levels 1 and 2.
        /// </summary>
        Skill1_2 = 0x0001,

        /// <summary>
        /// Thing is present on difficulty level 3.
        /// </summary>
        Skill3 = 0x0002,

        /// <summary>
        /// Thing is present on difficulty levels 4 and 5.
        /// </summary>
        Skill4_5 = 0x0004,

        /// <summary>
        /// Thing is lying in Ambush.
        /// </summary>
        Ambush = 0x0008,

        /// <summary>
        /// Thing is dormant until activated.
        /// </summary>
        Dormant = 0x0010,

        /// <summary>
        /// Thing is spawned when playing a Fighter.
        /// </summary>
        Fighter = 0x0020,

        /// <summary>
        /// Thing is spawned when playing a Cleric.
        /// </summary>
        Cleric = 0x0040,

        /// <summary>
        /// Thing is spawned when playing a Mage.
        /// </summary>
        Mage = 0x0080,

        /// <summary>
        /// Thing is present in single player.
        /// </summary>
        SinglePlayer = 0x0100,

        /// <summary>
        /// Thing is present in cooperative.
        /// </summary>
        Cooperative = 0x0200,

        /// <summary>
        /// Thing is present in deathmatch.
        /// </summary>
        Deathmatch = 0x0400,

        /// <summary>
        /// Thing is see-through.
        /// </summary>
        Translucent = 0x0800,

        /// <summary>
        /// Thing is invisible.
        /// </summary>
        Invisible = 0x1000,

        /// <summary>
        /// Thing is non-hostile.
        /// </summary>
        Friendly = 0x2000,

        /// <summary>
        /// Thing is stationary.
        /// </summary>
        StandStill = 0x4000
    }
}
